#include "disp.h"
#include "dis_pic.h"
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
#include "u8g2.h"
#include "ui.h"
#include "stdio.h"
#include "string.h"
#include "semphr.h"

extern EventGroupHandle_t WIFI_connected_Handle;
extern SemaphoreHandle_t Mutex_Handle;
extern EventGroupHandle_t ESP_EventGroup_Handle;
extern EventGroupHandle_t TimeRefresh_Handle;
extern TaskHandle_t u8g2_show_Handle;
extern TaskHandle_t show_one_Handle;
extern TaskHandle_t show_two_Handle;
extern uint8_t key_num;
MYTime time = {23,59,57};
uint8_t last_min = 0;
uint8_t key_last = 0;
uint8_t key_old = 1;
menu_option_Typedef menu_option_list[] = {{"temp",NULL,NULL,NULL,NULL,temp_img, temp_img_small},
                                        {"pres",NULL,NULL,NULL,NULL,pressure_img,pressure_img_small},
                                        {"light",NULL,NULL,NULL,NULL,light_img,light_img_small}};
menu_Typedef first_menu;
void show_string(const uint8_t *font, uint8_t x, uint8_t y, const char *str)
{//u8g2_font_6x13_tf
    u8g2_SetFont(&u8g2, font);    
    u8g2_DrawStr(&u8g2, x, y, str);
    u8g2_SendBuffer(&u8g2);  
}
//添加菜单项
void Add_Menu(menu_Typedef *addmenu,char *menu_name, char *option_name, menu_Typedef *par_menu)
{
    addmenu ->name = menu_name;
    addmenu ->parent_menu = par_menu;
    addmenu ->current_index = 0;

    if(addmenu ->parent_menu == NULL)
    {
        return;
    }
    menu_option_Typedef *par_option = par_menu ->option;
    while(par_option != NULL)
    {
        if(strcmp(par_option ->option_name, option_name) == 0)
        {
            par_option ->child_menu = addmenu;
        }
        par_option = par_option ->next_option;
    }
    

}
//往某一级菜单里面添加option选项
void Add_option(menu_Typedef *menu, menu_option_Typedef *option_list, uint8_t listnum)
{
    menu ->num = listnum;
    menu ->option = &option_list[0];
    for(uint8_t i = 1; i < listnum; i++)
    {
        option_list[i-1].next_option = &option_list[i];
        option_list[i].pre_option = &option_list[i-1];
    }
}
void create_menu(void)
{
    Add_Menu(&first_menu, "first_menu", NULL, NULL);
    Add_option(&first_menu, menu_option_list, 3);
}
void draw_menu(menu_Typedef *menu,uint8_t i)
{
    u8g2_SetFont(&u8g2, u8g2_font_6x13_tf);
    //显示小的图片
    menu_option_Typedef *option = &menu->option[i%3];
    show_pic(&u8g2, 0, 10, 36, 36, option->option_img_small);
    show_string(u8g2_font_6x13_tf, 7, 61, option->option_name);
    //显示大的图片
    option = &menu->option[(i+1)%3];
    show_pic(&u8g2, 40, 4, 48, 48, option->option_img);
    show_string(u8g2_font_6x13_tf, 54, 61, option->option_name);
    //显示小的图片
    option = &menu->option[(i+2)%3];
    show_pic(&u8g2, 88, 10, 36, 36, option->option_img_small);
    show_string(u8g2_font_6x13_tf, 93, 61, option->option_name);
  
}
//一次性任务，初始化之后就删掉去，不知道为什么这个只能在任务中初始化，
//在外面初始化就直接卡死程序，可能是因为开始调度之后，才会开启时钟
//而且在u8g2的初始化用了延时，只有在开启了任务调度才会有用
void u8g2_init_task(void *parameters)
{
    for(;;)
    {   
        create_menu();
        u8g2_Init(&u8g2);
        vTaskDelay(20);
        vTaskDelete(NULL);
    }
}
void caltime(void)
{
    if(time.sec >= 60)
    {   
        time.sec = 0;
        time.min++;
        if(time.min >= 60)
        {
            time.min = 0;
            time.hour++;
            if(time.hour >= 23)
            {
                time.hour = 0;
            }
        }
    }
}
void remove_little_shadow(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
{
    u8g2_SetDrawColor(&u8g2, 0);
    u8g2_DrawBox(&u8g2, x, y, w, h);  
    u8g2_SendBuffer(&u8g2);   
    u8g2_SetDrawColor(&u8g2, 1);   
}
void show_mqtt_connecting(void)
{
    uint8_t show_flag = 0;
    EventBits_t bitset = xEventGroupGetBits(WIFI_connected_Handle);
    EventBits_t bitmqtoset = xEventGroupGetBits(ESP_EventGroup_Handle);

    show_flag = ((bitmqtoset & (1 << 2)) && (bitset & (1 << 4))) ? 2 : 0;
    if(show_flag != 2)
    {
        show_flag = (bitset & (1 << 4)) ? 1 : 0;   
    }
    switch (show_flag)
    {
    case  0:

        remove_little_shadow(97, 0, 24, 13);
        show_string(u8g2_font_6x13_tf, 97, 12, "M");
        show_string(u8g2_font_6x13_tf, 15, 12, "x");
        show_string(u8g2_font_6x13_tf, 121, 12, "x");
        show_pic(&u8g2, 0, 0, 15, 12, wifipic1_2);
        vTaskDelay(20);
        show_string(u8g2_font_6x13_tf, 97, 12, "MQ");
        show_pic(&u8g2, 0, 0, 15, 12, wifipic3_4);
        vTaskDelay(20);
        show_string(u8g2_font_6x13_tf, 97, 12, "MQT");
        show_pic(&u8g2, 0, 0, 15, 12, wifipic_all);
        vTaskDelay(20); 
        show_string(u8g2_font_6x13_tf, 97, 12, "MQTT");

        break;
    case 1:

        remove_little_shadow(97, 0, 24, 13);
        remove_little_shadow(13, 6, 7, 7);
        show_pic(&u8g2, 0, 0, 15, 12, wifipic_all);
        show_string(u8g2_font_6x13_tf, 97, 12, "M");
        show_string(u8g2_font_6x13_tf, 121, 12, "x");
        show_string(u8g2_font_6x13_tf, 97, 12, "MQT");
        show_string(u8g2_font_6x13_tf, 97, 12 ,"MQTT");
        break;   

    case 2:

        remove_little_shadow(13, 6, 7, 7);
        show_pic(&u8g2, 0, 0, 15, 12, wifipic_all);
        remove_little_shadow(121, 6, 7, 7);
        show_string(u8g2_font_6x13_tf, 97, 12, "MQTT");
 
        break;    

    default:
        break;
    }
    
}
void remove_shadow(void)
{
    if(last_min != time.min)
    {
        
        if((last_min %10 ) != 9)
        {
            remove_little_shadow(99, 13, 28, 39);
        }
        else if((last_min % 10 == 9) && (last_min != 59))
        {  
            remove_little_shadow(68, 13, 68, 39);                  
        }
        else
        { 
            remove_little_shadow(0, 13, 128, 39);                 
        }
        last_min = time.min;             
    } 
}

//切换页面的函数
void change_mainpage(void)
{
    if(key_last != key_num)
    {
        key_last = key_num;
        if((key_num + 3) % 4 == 3)
        {   //只有获取到锁之后才表示其他任务没有持有锁，才可以把它们挂起来
            BaseType_t lock_ret = xSemaphoreTake(Mutex_Handle, portMAX_DELAY);
            if(lock_ret != NULL)
            {
                vTaskResume(show_one_Handle);
                vTaskResume(u8g2_show_Handle);
                eTaskState ret = eTaskGetState(show_two_Handle);
                if(ret != eSuspended)
                {
                    vTaskSuspend(show_two_Handle);
                }
                u8g2_ClearBuffer(&u8g2);
                xSemaphoreGive(Mutex_Handle);
            }

        }
        if((key_num + 3) % 4 != 3)
        {
            BaseType_t lock_ret = xSemaphoreTake(Mutex_Handle, portMAX_DELAY);
            if(lock_ret != NULL)
            {
                vTaskResume(show_two_Handle);
                vTaskResume(show_two_Handle);
                eTaskState ret = eTaskGetState(u8g2_show_Handle);
                if(ret != eSuspended)
                {                 
                    u8g2_ClearBuffer(&u8g2);
                    vTaskSuspend(show_one_Handle);
                    vTaskSuspend(u8g2_show_Handle);                
                }
                xSemaphoreGive(Mutex_Handle);
            }
        }
    }
}
//下面两个任务是主界面的显示
void ui_show_task(void *parameters)
{
    char timebuf[128];
    
    for(;;)
    {   //主页时间的显示
        EventBits_t time_get_bit= xEventGroupWaitBits(TimeRefresh_Handle, 1 << 0, pdTRUE, pdTRUE, pdMS_TO_TICKS(50));
        if((time_get_bit & (1 << 0)) == (1 << 0))
        {
            u8g2_ClearBuffer(&u8g2);
        }
        caltime();
        sprintf(timebuf, "%02d %02d",time.hour, time.min);
        BaseType_t ret = xSemaphoreTake(Mutex_Handle, pdMS_TO_TICKS(60));
        if(ret == pdTRUE)
        {
            remove_shadow();
            show_string(u8g2_font_osb35_tf, 0, 51, (char *)timebuf);
            memset(timebuf, 0, sizeof(timebuf));
            show_string(u8g2_font_osb35_tf, 56, 46, ":");
            xSemaphoreGive(Mutex_Handle);
        }    
        vTaskDelay(20);
    }
}

void show_one_Task(void *parameters)
{
    
    for(;;)
    {
        BaseType_t ret = xSemaphoreTake(Mutex_Handle, pdMS_TO_TICKS(50));
        if(ret == pdTRUE)
        {
            show_mqtt_connecting();
            remove_little_shadow(58, 23, 10, 24);
            xSemaphoreGive(Mutex_Handle);
        }
        vTaskDelay(20);
    }
}
void show_two_task(void *parameters)
{
    for(;;)
    {
        
        if(key_old != key_num)
        {
            key_old = key_num;
            BaseType_t ret = xSemaphoreTake(Mutex_Handle, pdMS_TO_TICKS(50));
            if(ret == pdTRUE)
            {
                remove_little_shadow(0, 0,127, 63);
                draw_menu(&first_menu,key_num);  
                xSemaphoreGive(Mutex_Handle);
            }  
        }
        vTaskDelay(20);
    }
}